import 'dart:convert';

import 'package:base_app/commons/widgets/webview/web_view_js.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';

import 'js_message.dart';

class InAppWebJSHandlerManager {
  //flutter_inappwebview插件
  InAppWebViewController? inAppWebViewController;

  BuildContext? context;

  // 存储的消息messageHandler
  Map<String, dynamic> messageHandlers = {};

  // 存储的回调callback， responseCallback
  Map<String, dynamic> responseCallbacks = {};

  // 开启的消息队列，发生的消息均会存储到该队列中
  List<JSMessage>? startupMessageQueue = [];

  // 消息的标识
  int _uniqueId = 0;



  InAppWebJSHandlerManager() {
    //TODO
  }

  void updateController({
    required BuildContext context,
    InAppWebViewController? inAppWebViewController,
  }) {
    this.context = context;
    this.inAppWebViewController = inAppWebViewController;
  }

  void flutterFlushMessageQueue() async {
    String? messageQueueString;
    if (inAppWebViewController != null) {
      messageQueueString = await inAppWebViewController!
          .evaluateJavascript(source: webViewJavascriptFetchQueryCommand());
    }
    flushMessageQueue(messageQueueString);
  }

  void flushMessageQueue(String? messageQueueString) {
    if (messageQueueString == null || messageQueueString.isEmpty) {
      return;
    }
    var fromWebMessage = jsonDecode(messageQueueString);
    if (fromWebMessage != null && fromWebMessage is List) {
      for (dynamic aMsgJson in fromWebMessage) {
        if (aMsgJson is Map<String, dynamic>) {
          JSMessage jsMessage = JSMessage.fromJson(aMsgJson);

          // 从H5获取或者接收到的消息，如果responseId不为空，则为flutter调用H5方法，H5给flutter的回调
          if (jsMessage.responseId != null &&
              jsMessage.responseId!.isNotEmpty) {
            // 如果responseId不为空，则为flutter调用H5方法，H5给flutter的回调
            var responseCallback = responseCallbacks[jsMessage.responseId];
            if (responseCallback != null) {
              // 处理H5返回给flutter的回调
              responseCallback(jsMessage.responseData);
            }
          } else {
            var responseCallback;
            // 如果responseId为空时候，则是来自H5发送的flutter的消息
            // 获取H5传过来的标识callbackId
            String? callbackId = jsMessage.callbackId;
            if (callbackId != null && callbackId.isNotEmpty) {
              // 接收到来自H5的消息
              JSMessage aMessage = JSMessage();
              aMessage.copy(aNewMessage: aMessage, aOldMessage: jsMessage);

              responseCallback = (dynamic responseData) {
                // flutter回调给H5
                // 将H5传过来的callbackId作为responseId回调传递给H5
                aMessage.responseId = callbackId;
                aMessage.responseData = responseData;
                _queueMessage(aMessage);
              };
            } else {
              responseCallback = (dynamic responseData) {
                // callbackId为空，不做任何处理
              };
            }

            // 从flutter已经注册Register方法中找出对应的方法
            dynamic jsBridgeHandler = messageHandlers[jsMessage.handlerName];
            if(null != jsBridgeHandler){
              // 在flutter该handlerName的方法已经注册register
              jsBridgeHandler(jsMessage.data, responseCallback);
            }
          }
        }
      }
    }
  }

  void _dispatchMessage(JSMessage message) async {
    String messageJSON = jsonEncode(message.toJson());

    messageJSON = messageJSON.replaceAll("\\", "\\\\");
    messageJSON = messageJSON.replaceAll("\"", "\\\"");
    messageJSON = messageJSON.replaceAll("\'", "\\\'");
    messageJSON = messageJSON.replaceAll("\n", "\\n");
    messageJSON = messageJSON.replaceAll("\r", "\\r");
    messageJSON = messageJSON.replaceAll("\f", "\\f");
    messageJSON = messageJSON.replaceAll("\u2028", "\\u2028");
    messageJSON = messageJSON.replaceAll("\u2029", "\\u2029");

    String javascriptCommand =
        webViewJavascriptHandleMessageFromObjCCommand(messageJSON);

    if (inAppWebViewController != null) {
      await inAppWebViewController?.evaluateJavascript(
          source: javascriptCommand);
    }
  }

  // 注入js
  void injectJavascript(String javascript) async {
    if (inAppWebViewController != null) {
      await inAppWebViewController?.evaluateJavascript(source: javascript);
    }
  }

  //注入js
  void injectJavascriptReady() async {
    if (inAppWebViewController != null) {
      await inAppWebViewController?.evaluateJavascript(
          source: webviewJsBridgeReady);
    }
  }

  // 注入js
  void injectBridgeJavascript() async {
    if (inAppWebViewController != null) {
      await inAppWebViewController?.evaluateJavascript(
          source: webviewJavascriptBridge);
    }

    //LoggerManager().debug("injectJavascript");

    // 处理flutter发送的消息队列
    if (startupMessageQueue != null && startupMessageQueue!.isNotEmpty) {
      List<JSMessage> tmpList = startupMessageQueue!;
      startupMessageQueue = null;
      for (JSMessage message in tmpList) {
        _dispatchMessage(message);
      }
    }
  }

  // 向H5发送消息
  void _sendData(String handleName, {dynamic data, dynamic responseCallback}) {
    String callbackId = "flutter_cb_${++_uniqueId}";

    JSMessage jsMessage = JSMessage();
    jsMessage.callbackId = callbackId;
    jsMessage.handlerName = handleName;
    jsMessage.data = data;

    // 将callbackId存储到responseCallbacks中，callbackId会被H5通过responseId返回
    if (responseCallback != null) {
      responseCallbacks[callbackId] = responseCallback;
    }

    _queueMessage(jsMessage);
  }

  // 将发送给H5的消息存到startupMessageQueue中
  void _queueMessage(JSMessage jsMessage) {
    if (startupMessageQueue != null) {
      startupMessageQueue!.add(jsMessage);
    }
    _dispatchMessage(jsMessage);
  }

  // 注入js的command
  String webViewJavascriptCheckCommand() {
    return "typeof window.AppJSBridge == 'object';";
  }

  String webViewJavascriptFetchQueryCommand() {
    return "AppJSBridge._fetchQueue();";
  }

  String webViewJavascriptHandleMessageFromObjCCommand(String messageJSON) {
    return "AppJSBridge._handleMessageFromObjC('$messageJSON');";
  }

  // Future<void> addWebEvent(WebEvent webEvent) async {
  //   String js = '''
  //   window.dispatchEvent(new CustomEvent('${webEvent.eventName}', {detail:JSON.parse('${jsonEncode(webEvent.detail)}')}))
  //   ''';
  //   await inAppWebViewController?.evaluateJavascript(source: js);
  // }

  // 判断AppJSBridge
  Future<String?> checkJavascriptBridge() async {
    String? result;
    if (inAppWebViewController != null) {
      bool jsBridge = await inAppWebViewController?.evaluateJavascript(
          source: webViewJavascriptCheckCommand());
      result = (jsBridge ? "true" : "false");
    }
    //LoggerManager().debug("checkJavascriptBridge result:${result}");
    return result;
  }

  /// flutter开放出去的方法，flutter调用H5方法统一使用该callHandler
  /// callHandler
  void callHandler(String handleName, {var data, var responseCallback}) {
    if (handleName.isNotEmpty) {
      _sendData(handleName, data: data, responseCallback: responseCallback);
    }
  }

  /// flutter注册方法
  /// flutter注册方法，提供给H5调用
  void registerHandler(String handlerName, dynamic jsBridgeHandler) {
    if (handlerName.isNotEmpty) {
      messageHandlers[handlerName] = jsBridgeHandler;
    }
  }

  void addJSBridgeHandlers() {
    if (inAppWebViewController != null) {
      messageHandlers.forEach((handlerName, jsBridgeHandler) {
        inAppWebViewController?.addJavaScriptHandler(
            handlerName: handlerName,
            callback: (List<dynamic> arguments) {
              //LoggerManager().debug("inAppWebViewController.addJavaScriptHandler arguments:${arguments}");
              flutterFlushMessageQueue();
            });
      });
    }
  }

  // 移除注册的方法
  void removeHandler(String handleName) {
    if (handleName.isNotEmpty) {
      messageHandlers.remove(handleName);
    }
  }

  // 重置，将responseCallbacks、startupMessageQueue重置
  void reset() {
    startupMessageQueue = [];
    responseCallbacks = {};
    _uniqueId = 0;
  }
}
